package org.dyndns.opendemogroup.optimizer.problems;

import java.util.Random;

import org.dyndns.opendemogroup.optimizer.ArrayUtil;
import org.dyndns.opendemogroup.optimizer.ICustomCoding;
import org.dyndns.opendemogroup.optimizer.IOptimizationProblem;
import org.dyndns.opendemogroup.optimizer.Member;

/**
 * maximize (x1 * x2 * x3 * x4 * x5) / (x6 * x7 * x8 * x9 * x10), 1 <= xi <= 10
 */
public class SimpleMax implements IOptimizationProblem, ICustomCoding
{
	private int memberSize;

	private double[] parameters;

	public SimpleMax ( int memberSize )
	{
		this.memberSize = memberSize;
		parameters = new double[memberSize];
	}

	/**
	 * @see IOptimizationProblem#computeFitness(Random)
	 */
	public double computeFitness ( Random randomSource )
	{
		int halfPoint = memberSize / 2;
		long numerator = 1;
		long denominator = 1;
		for ( int i = 0; i < halfPoint; i++ )
		{
			numerator *= parameters[i];
			denominator *= parameters[i + halfPoint];
		}
		double fitness = numerator / denominator;
		return fitness;
	}

	/**
	 * @see IOptimizationProblem#getGeneRange()
	 */
	public int getGeneRange ( )
	{
		return 9;
	}

	/**
	 * @see IOptimizationProblem#getMemberSize()
	 */
	public int getMemberSize ( )
	{
		return memberSize;
	}

	/**
	 * @see IOptimizationProblem#isMaximizing()
	 */
	public boolean isMaximizing ( )
	{
		return true;
	}

	/**
	 * @see ICustomCoding#decodeFrom(Member)
	 */
	public void decodeFrom ( Member source )
	{
		ArrayUtil.copy ( source.genome, parameters, 0, memberSize - 1 );
		// { adjust values by adding one (genome stores 0-9, we want 1-10)
		for ( int i = 0; i < memberSize; i++ )
		{
			parameters[i]++;
		}
		// }
	}

	/**
	 * @see ICustomCoding#encodeTo(Member)
	 */
	public void encodeTo ( Member target )
	{
		ArrayUtil.copy ( parameters, target.genome, 0, memberSize - 1 );
		// { adjust values by subtracting one (we store 1-10, genome wants 0-9)
		for ( int i = 0; i < memberSize; i++ )
		{
			target.genome[i]--;
		}
		// }

	}

	public boolean isCombinatorialOptimization ( )
	{
		return false;
	}

	public boolean makeValid ( )
	{
		// do nothing on purpose
		return false;
	}

}
